View Javadoc
1   package edu.jiangxin.apktoolbox.file.password.recovery.checker;
2   
3   import org.apache.commons.compress.archivers.sevenz.SevenZArchiveEntry;
4   import org.apache.commons.compress.archivers.sevenz.SevenZFile;
5   import org.apache.commons.compress.utils.MultiReadOnlySeekableByteChannel;
6   import org.apache.commons.io.FilenameUtils;
7   import org.apache.commons.io.IOUtils;
8   
9   import java.io.BufferedInputStream;
10  import java.io.File;
11  import java.io.IOException;
12  import java.nio.channels.SeekableByteChannel;
13  import java.util.ArrayList;
14  import java.util.List;
15  
16  public final class SevenZipChecker extends FileChecker {
17      private static final boolean DEBUG = true;
18  
19      private boolean isSplitFile = false;
20  
21      private File[] splitFiles;
22  
23      public SevenZipChecker() {
24          super();
25      }
26  
27      @Override
28      public String[] getFileExtensions() {
29          return new String[]{"7z", "001"};
30      }
31  
32      @Override
33      public String getFileDescription() {
34          return "*.7z";
35      }
36  
37      @Override
38      public String getDescription() {
39          return "7Zip Checker";
40      }
41  
42      @Override
43      public boolean prepareChecker() {
44          return true;
45      }
46  
47      @Override
48      public void attachFile(File file) {
49          super.attachFile(file);
50          isSplitFile = isSplitFile();
51          splitFiles = getSplitFiles();
52      }
53  
54      @Override
55      public boolean checkPassword(String password) {
56          if (DEBUG) {
57              logger.info("checkPassword: " + password);
58          }
59          if (isSplitFile) {
60              SevenZFile.Builder builder = new SevenZFile.Builder();
61              SeekableByteChannel channel = null;
62              SevenZFile sevenZFile = null;
63              try {
64                  channel = MultiReadOnlySeekableByteChannel.forFiles(splitFiles);
65                  builder.setSeekableByteChannel(channel).setPassword(password.toCharArray());
66                  sevenZFile = builder.get();
67                  tryToRead(sevenZFile);
68                  return true;
69              } catch (IOException e) {
70                  return false;
71              } finally {
72                  IOUtils.closeQuietly(channel);
73                  IOUtils.closeQuietly(sevenZFile);
74              }
75  
76          } else {
77              SevenZFile sevenZFile = null;
78              try {
79                  SevenZFile.Builder builder = new SevenZFile.Builder().setFile(file).setPassword(password.toCharArray());
80                  builder.setFile(file).setPassword(password.toCharArray());
81                  sevenZFile = builder.get();
82                  tryToRead(sevenZFile);
83                  return true;
84              } catch (IOException e) {
85                  return false;
86              } finally {
87                  IOUtils.closeQuietly(sevenZFile);
88              }
89          }
90      }
91  
92      private void tryToRead(SevenZFile sevenZFile) throws IOException {
93          SevenZArchiveEntry entry = sevenZFile.getNextEntry();
94          while (entry != null) {
95              try (BufferedInputStream bis = new BufferedInputStream(sevenZFile.getInputStream(entry))) {
96                  byte[] buffer = new byte[1024];
97                  while (bis.read(buffer) != -1) {
98                      // do nothing
99                  }
100             }
101             entry = sevenZFile.getNextEntry();
102         }
103     }
104 
105     private boolean isSplitFile() {
106         String extension = FilenameUtils.getExtension(file.getName());
107         logger.info("isSplitFile extension: {}", extension);
108         return "001".equals(extension);
109     }
110 
111     private File[] getSplitFiles() {
112         List<File> fileList = new ArrayList<>();
113         String baseName = FilenameUtils.getBaseName(file.getName());
114         String parent = file.getParent();
115         logger.info("getSplitFiles baseName: {}", baseName);
116         for (int i = 1; i < 1000; i++) {
117             File file = new File(parent, baseName + "." + String.format("%03d", i));
118             if (file.exists()) {
119                 fileList.add(file);
120             } else {
121                 break;
122             }
123         }
124         logger.info("getSplitFiles: {}", fileList);
125         return fileList.toArray(new File[0]);
126     }
127 }